package hn.cch.apache.commons.compress;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.apache.commons.compress.archivers.zip.ZipSplitReadOnlySeekableByteChannel;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.SeekableByteChannel;
import java.util.Enumeration;


public class CompressTest {

    public static String dirPathName = "src/test/resources/dir";
    public static String zipFileName = "zip.zip";

    public static String pngFileName = "png.png";
    public static String txtFileName = "txt.txt";


    public File toFile(ZipArchiveEntry entry) throws IOException {
        File entryFile = new File(dirPathName, entry.getName());
        if (entry.isDirectory()) { // 文件夹
            if (!entryFile.exists() && !entryFile.mkdirs()) {
                throw new IOException("");
            }
        } else {
            File parentFile = entryFile.getParentFile();
            if (!parentFile.exists() && !parentFile.mkdirs()) {
                throw new IOException("");
            }

        }
        return entryFile;
    }

    /**
     * 解压
     *
     * @throws IOException
     */
    @Test
    public void testZipFile() throws IOException {

        // 解压
        try (ZipFile zipFile = new ZipFile(new File(dirPathName, zipFileName))) {
            Enumeration<ZipArchiveEntry> entries = zipFile.getEntries();
            ZipArchiveEntry archiveEntry = null;
            while (entries.hasMoreElements()) {
                archiveEntry = entries.nextElement();
                File entryFile = toFile(archiveEntry);
                if (entryFile == null) {
                    continue;
                }
                try (InputStream inputStream = zipFile.getInputStream(archiveEntry)) {
                    byte[] buffer = new byte[1024];
                    while (IOUtils.read(inputStream, buffer) > 0) {
                        FileUtils.writeByteArrayToFile(entryFile, buffer);
                    }
                }
            }
        }
    }

    @Test
    public void testZipArchiveInputStream() throws IOException {
        try (FileInputStream fileInputStream = new FileInputStream(new File(dirPathName, zipFileName));
             ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(fileInputStream)) {
            ZipArchiveEntry archiveEntry = null;
            while ((archiveEntry = zipArchiveInputStream.getNextZipEntry()) != null) {
                if (!zipArchiveInputStream.canReadEntryData(archiveEntry)) {
                    continue;
                }
                File entryFile = toFile(archiveEntry);
                if (entryFile == null) {
                    continue;
                }
                byte[] buffer = new byte[1024];
                while (zipArchiveInputStream.read() > 0) {
                    FileUtils.writeByteArrayToFile(entryFile, buffer);
                }
            }
        }
    }


    @Test
    public void testZipArchiveOutputStream() throws IOException {

        try (ZipArchiveOutputStream zipArchiveOutputStream = new ZipArchiveOutputStream(new File(dirPathName, zipFileName))) {
            File[] files = new File(dirPathName).listFiles();
            assert files != null;
            for (File file : files) {
                if (file.isDirectory()) {
                    continue;
                }
                ZipArchiveEntry archiveEntry = new ZipArchiveEntry(file.getName());
                zipArchiveOutputStream.putArchiveEntry(archiveEntry);
                zipArchiveOutputStream.closeArchiveEntry();
            }

        }
    }

    public void testSeekableByteChannel() throws IOException {
        // commons-compress>1.20.x:支持分卷压缩解压文件
        try (SeekableByteChannel seekableByteChannel = ZipSplitReadOnlySeekableByteChannel.buildFromLastSplitSegment(
                new File(dirPathName, zipFileName))) {

        }

        try (SeekableByteChannel seekableByteChannel = ZipSplitReadOnlySeekableByteChannel.forFiles(
                new File(dirPathName, "zip0.zip"), new File(dirPathName, "zip1.zip"))) {

        }

    }


}
